{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image Classification\n",
    "\n",
    "For this problem, we will MNIST dataset.\n",
    "http://yann.lecun.com/exdb/mnist/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'http://172.17.1.79:4040'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spark.sparkContext.uiWebUrl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df_training = (spark\n",
    "               .read\n",
    "               .options(header = False, inferSchema = True)\n",
    "               .csv(\"data/MNIST/mnist_train.csv\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_training.count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No of columns:  785 ['_c0', '_c1', '_c2', '_c3', '_c4', '_c5', '_c6', '_c7', '_c8', '_c9', '_c10', '_c11', '_c12', '_c13', '_c14', '_c15', '_c16', '_c17', '_c18', '_c19', '_c20', '_c21', '_c22', '_c23', '_c24', '_c25', '_c26', '_c27', '_c28', '_c29', '_c30', '_c31', '_c32', '_c33', '_c34', '_c35', '_c36', '_c37', '_c38', '_c39', '_c40', '_c41', '_c42', '_c43', '_c44', '_c45', '_c46', '_c47', '_c48', '_c49', '_c50', '_c51', '_c52', '_c53', '_c54', '_c55', '_c56', '_c57', '_c58', '_c59', '_c60', '_c61', '_c62', '_c63', '_c64', '_c65', '_c66', '_c67', '_c68', '_c69', '_c70', '_c71', '_c72', '_c73', '_c74', '_c75', '_c76', '_c77', '_c78', '_c79', '_c80', '_c81', '_c82', '_c83', '_c84', '_c85', '_c86', '_c87', '_c88', '_c89', '_c90', '_c91', '_c92', '_c93', '_c94', '_c95', '_c96', '_c97', '_c98', '_c99', '_c100', '_c101', '_c102', '_c103', '_c104', '_c105', '_c106', '_c107', '_c108', '_c109', '_c110', '_c111', '_c112', '_c113', '_c114', '_c115', '_c116', '_c117', '_c118', '_c119', '_c120', '_c121', '_c122', '_c123', '_c124', '_c125', '_c126', '_c127', '_c128', '_c129', '_c130', '_c131', '_c132', '_c133', '_c134', '_c135', '_c136', '_c137', '_c138', '_c139', '_c140', '_c141', '_c142', '_c143', '_c144', '_c145', '_c146', '_c147', '_c148', '_c149', '_c150', '_c151', '_c152', '_c153', '_c154', '_c155', '_c156', '_c157', '_c158', '_c159', '_c160', '_c161', '_c162', '_c163', '_c164', '_c165', '_c166', '_c167', '_c168', '_c169', '_c170', '_c171', '_c172', '_c173', '_c174', '_c175', '_c176', '_c177', '_c178', '_c179', '_c180', '_c181', '_c182', '_c183', '_c184', '_c185', '_c186', '_c187', '_c188', '_c189', '_c190', '_c191', '_c192', '_c193', '_c194', '_c195', '_c196', '_c197', '_c198', '_c199', '_c200', '_c201', '_c202', '_c203', '_c204', '_c205', '_c206', '_c207', '_c208', '_c209', '_c210', '_c211', '_c212', '_c213', '_c214', '_c215', '_c216', '_c217', '_c218', '_c219', '_c220', '_c221', '_c222', '_c223', '_c224', '_c225', '_c226', '_c227', '_c228', '_c229', '_c230', '_c231', '_c232', '_c233', '_c234', '_c235', '_c236', '_c237', '_c238', '_c239', '_c240', '_c241', '_c242', '_c243', '_c244', '_c245', '_c246', '_c247', '_c248', '_c249', '_c250', '_c251', '_c252', '_c253', '_c254', '_c255', '_c256', '_c257', '_c258', '_c259', '_c260', '_c261', '_c262', '_c263', '_c264', '_c265', '_c266', '_c267', '_c268', '_c269', '_c270', '_c271', '_c272', '_c273', '_c274', '_c275', '_c276', '_c277', '_c278', '_c279', '_c280', '_c281', '_c282', '_c283', '_c284', '_c285', '_c286', '_c287', '_c288', '_c289', '_c290', '_c291', '_c292', '_c293', '_c294', '_c295', '_c296', '_c297', '_c298', '_c299', '_c300', '_c301', '_c302', '_c303', '_c304', '_c305', '_c306', '_c307', '_c308', '_c309', '_c310', '_c311', '_c312', '_c313', '_c314', '_c315', '_c316', '_c317', '_c318', '_c319', '_c320', '_c321', '_c322', '_c323', '_c324', '_c325', '_c326', '_c327', '_c328', '_c329', '_c330', '_c331', '_c332', '_c333', '_c334', '_c335', '_c336', '_c337', '_c338', '_c339', '_c340', '_c341', '_c342', '_c343', '_c344', '_c345', '_c346', '_c347', '_c348', '_c349', '_c350', '_c351', '_c352', '_c353', '_c354', '_c355', '_c356', '_c357', '_c358', '_c359', '_c360', '_c361', '_c362', '_c363', '_c364', '_c365', '_c366', '_c367', '_c368', '_c369', '_c370', '_c371', '_c372', '_c373', '_c374', '_c375', '_c376', '_c377', '_c378', '_c379', '_c380', '_c381', '_c382', '_c383', '_c384', '_c385', '_c386', '_c387', '_c388', '_c389', '_c390', '_c391', '_c392', '_c393', '_c394', '_c395', '_c396', '_c397', '_c398', '_c399', '_c400', '_c401', '_c402', '_c403', '_c404', '_c405', '_c406', '_c407', '_c408', '_c409', '_c410', '_c411', '_c412', '_c413', '_c414', '_c415', '_c416', '_c417', '_c418', '_c419', '_c420', '_c421', '_c422', '_c423', '_c424', '_c425', '_c426', '_c427', '_c428', '_c429', '_c430', '_c431', '_c432', '_c433', '_c434', '_c435', '_c436', '_c437', '_c438', '_c439', '_c440', '_c441', '_c442', '_c443', '_c444', '_c445', '_c446', '_c447', '_c448', '_c449', '_c450', '_c451', '_c452', '_c453', '_c454', '_c455', '_c456', '_c457', '_c458', '_c459', '_c460', '_c461', '_c462', '_c463', '_c464', '_c465', '_c466', '_c467', '_c468', '_c469', '_c470', '_c471', '_c472', '_c473', '_c474', '_c475', '_c476', '_c477', '_c478', '_c479', '_c480', '_c481', '_c482', '_c483', '_c484', '_c485', '_c486', '_c487', '_c488', '_c489', '_c490', '_c491', '_c492', '_c493', '_c494', '_c495', '_c496', '_c497', '_c498', '_c499', '_c500', '_c501', '_c502', '_c503', '_c504', '_c505', '_c506', '_c507', '_c508', '_c509', '_c510', '_c511', '_c512', '_c513', '_c514', '_c515', '_c516', '_c517', '_c518', '_c519', '_c520', '_c521', '_c522', '_c523', '_c524', '_c525', '_c526', '_c527', '_c528', '_c529', '_c530', '_c531', '_c532', '_c533', '_c534', '_c535', '_c536', '_c537', '_c538', '_c539', '_c540', '_c541', '_c542', '_c543', '_c544', '_c545', '_c546', '_c547', '_c548', '_c549', '_c550', '_c551', '_c552', '_c553', '_c554', '_c555', '_c556', '_c557', '_c558', '_c559', '_c560', '_c561', '_c562', '_c563', '_c564', '_c565', '_c566', '_c567', '_c568', '_c569', '_c570', '_c571', '_c572', '_c573', '_c574', '_c575', '_c576', '_c577', '_c578', '_c579', '_c580', '_c581', '_c582', '_c583', '_c584', '_c585', '_c586', '_c587', '_c588', '_c589', '_c590', '_c591', '_c592', '_c593', '_c594', '_c595', '_c596', '_c597', '_c598', '_c599', '_c600', '_c601', '_c602', '_c603', '_c604', '_c605', '_c606', '_c607', '_c608', '_c609', '_c610', '_c611', '_c612', '_c613', '_c614', '_c615', '_c616', '_c617', '_c618', '_c619', '_c620', '_c621', '_c622', '_c623', '_c624', '_c625', '_c626', '_c627', '_c628', '_c629', '_c630', '_c631', '_c632', '_c633', '_c634', '_c635', '_c636', '_c637', '_c638', '_c639', '_c640', '_c641', '_c642', '_c643', '_c644', '_c645', '_c646', '_c647', '_c648', '_c649', '_c650', '_c651', '_c652', '_c653', '_c654', '_c655', '_c656', '_c657', '_c658', '_c659', '_c660', '_c661', '_c662', '_c663', '_c664', '_c665', '_c666', '_c667', '_c668', '_c669', '_c670', '_c671', '_c672', '_c673', '_c674', '_c675', '_c676', '_c677', '_c678', '_c679', '_c680', '_c681', '_c682', '_c683', '_c684', '_c685', '_c686', '_c687', '_c688', '_c689', '_c690', '_c691', '_c692', '_c693', '_c694', '_c695', '_c696', '_c697', '_c698', '_c699', '_c700', '_c701', '_c702', '_c703', '_c704', '_c705', '_c706', '_c707', '_c708', '_c709', '_c710', '_c711', '_c712', '_c713', '_c714', '_c715', '_c716', '_c717', '_c718', '_c719', '_c720', '_c721', '_c722', '_c723', '_c724', '_c725', '_c726', '_c727', '_c728', '_c729', '_c730', '_c731', '_c732', '_c733', '_c734', '_c735', '_c736', '_c737', '_c738', '_c739', '_c740', '_c741', '_c742', '_c743', '_c744', '_c745', '_c746', '_c747', '_c748', '_c749', '_c750', '_c751', '_c752', '_c753', '_c754', '_c755', '_c756', '_c757', '_c758', '_c759', '_c760', '_c761', '_c762', '_c763', '_c764', '_c765', '_c766', '_c767', '_c768', '_c769', '_c770', '_c771', '_c772', '_c773', '_c774', '_c775', '_c776', '_c777', '_c778', '_c779', '_c780', '_c781', '_c782', '_c783', '_c784']\n"
     ]
    }
   ],
   "source": [
    "print(\"No of columns: \", len(df_training.columns), df_training.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['_c1', '_c2', '_c3', '_c4', '_c5', '_c6', '_c7', '_c8', '_c9', '_c10', '_c11', '_c12', '_c13', '_c14', '_c15', '_c16', '_c17', '_c18', '_c19', '_c20', '_c21', '_c22', '_c23', '_c24', '_c25', '_c26', '_c27', '_c28', '_c29', '_c30', '_c31', '_c32', '_c33', '_c34', '_c35', '_c36', '_c37', '_c38', '_c39', '_c40', '_c41', '_c42', '_c43', '_c44', '_c45', '_c46', '_c47', '_c48', '_c49', '_c50', '_c51', '_c52', '_c53', '_c54', '_c55', '_c56', '_c57', '_c58', '_c59', '_c60', '_c61', '_c62', '_c63', '_c64', '_c65', '_c66', '_c67', '_c68', '_c69', '_c70', '_c71', '_c72', '_c73', '_c74', '_c75', '_c76', '_c77', '_c78', '_c79', '_c80', '_c81', '_c82', '_c83', '_c84', '_c85', '_c86', '_c87', '_c88', '_c89', '_c90', '_c91', '_c92', '_c93', '_c94', '_c95', '_c96', '_c97', '_c98', '_c99', '_c100', '_c101', '_c102', '_c103', '_c104', '_c105', '_c106', '_c107', '_c108', '_c109', '_c110', '_c111', '_c112', '_c113', '_c114', '_c115', '_c116', '_c117', '_c118', '_c119', '_c120', '_c121', '_c122', '_c123', '_c124', '_c125', '_c126', '_c127', '_c128', '_c129', '_c130', '_c131', '_c132', '_c133', '_c134', '_c135', '_c136', '_c137', '_c138', '_c139', '_c140', '_c141', '_c142', '_c143', '_c144', '_c145', '_c146', '_c147', '_c148', '_c149', '_c150', '_c151', '_c152', '_c153', '_c154', '_c155', '_c156', '_c157', '_c158', '_c159', '_c160', '_c161', '_c162', '_c163', '_c164', '_c165', '_c166', '_c167', '_c168', '_c169', '_c170', '_c171', '_c172', '_c173', '_c174', '_c175', '_c176', '_c177', '_c178', '_c179', '_c180', '_c181', '_c182', '_c183', '_c184', '_c185', '_c186', '_c187', '_c188', '_c189', '_c190', '_c191', '_c192', '_c193', '_c194', '_c195', '_c196', '_c197', '_c198', '_c199', '_c200', '_c201', '_c202', '_c203', '_c204', '_c205', '_c206', '_c207', '_c208', '_c209', '_c210', '_c211', '_c212', '_c213', '_c214', '_c215', '_c216', '_c217', '_c218', '_c219', '_c220', '_c221', '_c222', '_c223', '_c224', '_c225', '_c226', '_c227', '_c228', '_c229', '_c230', '_c231', '_c232', '_c233', '_c234', '_c235', '_c236', '_c237', '_c238', '_c239', '_c240', '_c241', '_c242', '_c243', '_c244', '_c245', '_c246', '_c247', '_c248', '_c249', '_c250', '_c251', '_c252', '_c253', '_c254', '_c255', '_c256', '_c257', '_c258', '_c259', '_c260', '_c261', '_c262', '_c263', '_c264', '_c265', '_c266', '_c267', '_c268', '_c269', '_c270', '_c271', '_c272', '_c273', '_c274', '_c275', '_c276', '_c277', '_c278', '_c279', '_c280', '_c281', '_c282', '_c283', '_c284', '_c285', '_c286', '_c287', '_c288', '_c289', '_c290', '_c291', '_c292', '_c293', '_c294', '_c295', '_c296', '_c297', '_c298', '_c299', '_c300', '_c301', '_c302', '_c303', '_c304', '_c305', '_c306', '_c307', '_c308', '_c309', '_c310', '_c311', '_c312', '_c313', '_c314', '_c315', '_c316', '_c317', '_c318', '_c319', '_c320', '_c321', '_c322', '_c323', '_c324', '_c325', '_c326', '_c327', '_c328', '_c329', '_c330', '_c331', '_c332', '_c333', '_c334', '_c335', '_c336', '_c337', '_c338', '_c339', '_c340', '_c341', '_c342', '_c343', '_c344', '_c345', '_c346', '_c347', '_c348', '_c349', '_c350', '_c351', '_c352', '_c353', '_c354', '_c355', '_c356', '_c357', '_c358', '_c359', '_c360', '_c361', '_c362', '_c363', '_c364', '_c365', '_c366', '_c367', '_c368', '_c369', '_c370', '_c371', '_c372', '_c373', '_c374', '_c375', '_c376', '_c377', '_c378', '_c379', '_c380', '_c381', '_c382', '_c383', '_c384', '_c385', '_c386', '_c387', '_c388', '_c389', '_c390', '_c391', '_c392', '_c393', '_c394', '_c395', '_c396', '_c397', '_c398', '_c399', '_c400', '_c401', '_c402', '_c403', '_c404', '_c405', '_c406', '_c407', '_c408', '_c409', '_c410', '_c411', '_c412', '_c413', '_c414', '_c415', '_c416', '_c417', '_c418', '_c419', '_c420', '_c421', '_c422', '_c423', '_c424', '_c425', '_c426', '_c427', '_c428', '_c429', '_c430', '_c431', '_c432', '_c433', '_c434', '_c435', '_c436', '_c437', '_c438', '_c439', '_c440', '_c441', '_c442', '_c443', '_c444', '_c445', '_c446', '_c447', '_c448', '_c449', '_c450', '_c451', '_c452', '_c453', '_c454', '_c455', '_c456', '_c457', '_c458', '_c459', '_c460', '_c461', '_c462', '_c463', '_c464', '_c465', '_c466', '_c467', '_c468', '_c469', '_c470', '_c471', '_c472', '_c473', '_c474', '_c475', '_c476', '_c477', '_c478', '_c479', '_c480', '_c481', '_c482', '_c483', '_c484', '_c485', '_c486', '_c487', '_c488', '_c489', '_c490', '_c491', '_c492', '_c493', '_c494', '_c495', '_c496', '_c497', '_c498', '_c499', '_c500', '_c501', '_c502', '_c503', '_c504', '_c505', '_c506', '_c507', '_c508', '_c509', '_c510', '_c511', '_c512', '_c513', '_c514', '_c515', '_c516', '_c517', '_c518', '_c519', '_c520', '_c521', '_c522', '_c523', '_c524', '_c525', '_c526', '_c527', '_c528', '_c529', '_c530', '_c531', '_c532', '_c533', '_c534', '_c535', '_c536', '_c537', '_c538', '_c539', '_c540', '_c541', '_c542', '_c543', '_c544', '_c545', '_c546', '_c547', '_c548', '_c549', '_c550', '_c551', '_c552', '_c553', '_c554', '_c555', '_c556', '_c557', '_c558', '_c559', '_c560', '_c561', '_c562', '_c563', '_c564', '_c565', '_c566', '_c567', '_c568', '_c569', '_c570', '_c571', '_c572', '_c573', '_c574', '_c575', '_c576', '_c577', '_c578', '_c579', '_c580', '_c581', '_c582', '_c583', '_c584', '_c585', '_c586', '_c587', '_c588', '_c589', '_c590', '_c591', '_c592', '_c593', '_c594', '_c595', '_c596', '_c597', '_c598', '_c599', '_c600', '_c601', '_c602', '_c603', '_c604', '_c605', '_c606', '_c607', '_c608', '_c609', '_c610', '_c611', '_c612', '_c613', '_c614', '_c615', '_c616', '_c617', '_c618', '_c619', '_c620', '_c621', '_c622', '_c623', '_c624', '_c625', '_c626', '_c627', '_c628', '_c629', '_c630', '_c631', '_c632', '_c633', '_c634', '_c635', '_c636', '_c637', '_c638', '_c639', '_c640', '_c641', '_c642', '_c643', '_c644', '_c645', '_c646', '_c647', '_c648', '_c649', '_c650', '_c651', '_c652', '_c653', '_c654', '_c655', '_c656', '_c657', '_c658', '_c659', '_c660', '_c661', '_c662', '_c663', '_c664', '_c665', '_c666', '_c667', '_c668', '_c669', '_c670', '_c671', '_c672', '_c673', '_c674', '_c675', '_c676', '_c677', '_c678', '_c679', '_c680', '_c681', '_c682', '_c683', '_c684', '_c685', '_c686', '_c687', '_c688', '_c689', '_c690', '_c691', '_c692', '_c693', '_c694', '_c695', '_c696', '_c697', '_c698', '_c699', '_c700', '_c701', '_c702', '_c703', '_c704', '_c705', '_c706', '_c707', '_c708', '_c709', '_c710', '_c711', '_c712', '_c713', '_c714', '_c715', '_c716', '_c717', '_c718', '_c719', '_c720', '_c721', '_c722', '_c723', '_c724', '_c725', '_c726', '_c727', '_c728', '_c729', '_c730', '_c731', '_c732', '_c733', '_c734', '_c735', '_c736', '_c737', '_c738', '_c739', '_c740', '_c741', '_c742', '_c743', '_c744', '_c745', '_c746', '_c747', '_c748', '_c749', '_c750', '_c751', '_c752', '_c753', '_c754', '_c755', '_c756', '_c757', '_c758', '_c759', '_c760', '_c761', '_c762', '_c763', '_c764', '_c765', '_c766', '_c767', '_c768', '_c769', '_c770', '_c771', '_c772', '_c773', '_c774', '_c775', '_c776', '_c777', '_c778', '_c779', '_c780', '_c781', '_c782', '_c783', '_c784']\n"
     ]
    }
   ],
   "source": [
    "feature_culumns = [\"_c\" + str(i+1) for i in range(784)]\n",
    "print(feature_culumns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pyspark.ml.feature import VectorAssembler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-----+--------------------+\n",
      "|label|            features|\n",
      "+-----+--------------------+\n",
      "|    5|(784,[152,153,154...|\n",
      "|    0|(784,[127,128,129...|\n",
      "|    4|(784,[160,161,162...|\n",
      "|    1|(784,[158,159,160...|\n",
      "|    9|(784,[208,209,210...|\n",
      "|    2|(784,[155,156,157...|\n",
      "|    1|(784,[124,125,126...|\n",
      "|    3|(784,[151,152,153...|\n",
      "|    1|(784,[152,153,154...|\n",
      "|    4|(784,[134,135,161...|\n",
      "|    3|(784,[123,124,125...|\n",
      "|    5|(784,[216,217,218...|\n",
      "|    3|(784,[143,144,145...|\n",
      "|    6|(784,[72,73,74,99...|\n",
      "|    1|(784,[151,152,153...|\n",
      "|    7|(784,[211,212,213...|\n",
      "|    2|(784,[151,152,153...|\n",
      "|    8|(784,[159,160,161...|\n",
      "|    6|(784,[100,101,102...|\n",
      "|    9|(784,[209,210,211...|\n",
      "+-----+--------------------+\n",
      "only showing top 20 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "vectorizer = VectorAssembler(inputCols=feature_culumns, outputCol=\"features\")\n",
    "training = (vectorizer\n",
    "            .transform(df_training)\n",
    "            .select(\"_c0\", \"features\")\n",
    "            .toDF(\"label\", \"features\")\n",
    "            .cache())\n",
    "training.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = training.first().features.toArray()\n",
    "type(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x11b842080>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nRK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1337ed1d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(a.reshape(28, 28), cmap=\"Greys\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nN900itdYY43WDRYVKb6cWbzON5+VVw7/yfj5sGjRoqDvo48+iuLbb7896Js/f37QnjTpm42E2rdv\nX9BYAADC0mTEAAAgAElEQVSoJPH3tg8++CCKN95446CvnO91XPkFAABAZjD5BQAAQGZUZdnDsmXL\noviII44I+vyPpVdbbbWgb6WVvpnrx5evuvzyy5uMJenHP/5xFD/44INB35prrlnosFFB4iUxfj50\n6NAh6Dv33HOj+Ic//GHQ99///d9RfN111wV9p59+ehR/8cUXQd8jjzwStPfee+8ovvvuu4O+1Vdf\n/dtPABXB/71eeumlQZ//+z/88MODPn/Hv549ewZ9e+21V8Hnb9euXRQnXZIPxbdw4cIo/tWvfhX0\n+e8nRx99dN7HePjhh4P2f/7znyg+8sgjg77OnTsnGidQDHPnzo3iurq6oO/DDz+M4ni+X3XVVaUd\nWDO48gsAAIDMYPILAACAzGDyCwAAgMyoyppfv643vkTVRhttFMXxely/ljO+xMaTTz4ZxbfddlvQ\nd80110TxJZdcEvT94Q9/KGzQqCjDhg0L2t///vej+Ljjjgv6Cq3rPumkk4K2Xw/s1/RKYU2gFNb3\nxc8/duzYgs6P0osvkXj++edH8dlnnx30+d8xqK+vD/ri7aROOOGEKB44cGDQt+OOO0axXxssfXvJ\nPhTXvHnzoviee+4J+vz26NGjg75C67ZPO+20oH388cdH8b777hv09e3bN2ivuuqqBZ0D2fb0008H\n7X/84x95j/W/J7XbbrsFff53WK699tqgj5pfAAAAIAVMfgEAAJAZVfnZl/9x4k9+8pOiPGa/fv2i\nOP4xkb+EVUNDQ1HOh/IaN25cyc+x7bbbRrG/vJEk3XfffXnv5y8Ng8ry5ZdfBm2/1MF/XZKktdde\nO+/j+Ms1+jsBttYVV1zRZBznL60mSfvss08Ux8ts1lprrShm+bRkOnXqFMX+z1OSFi9enPd+/rF7\n7LFH3uP+7//+L2j7v/srr7wy6Ntpp52C9q677hrFp5xyStBHOUx2PfbYY0HbzxNJ+vrrr/Pe1y97\n8EtwJOmAAw6I4rvuuqstQywqrvwCAAAgM5j8AgAAIDOY/AIAACAzKPDJef/996P45JNPDvr8Wpc3\n3ngjtTEBqCzxmsjDDjssil977bWgL15D5/vss8+iePLkyXmP+/Of/xy048sPLViwIP9gPc8++2ze\n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\npJVW4v8Ttez9998P2g899FDeYz/88MMo/s1vflPwObbddtugffHFF0fxT37yk4IfB+W12WabRXFr\ntkX3t0KO112OHj06aP/85z+P4unTpwd9/naks2bNCvrWXnvtgseD6rJo0aKgff755wft//3f/43i\nNdZYI+i78cYbo7h9+/ZBn1+vufLKTB1qTfz3HV+izH+t2WKLLYK+ESNGRLFzLuhr7v1rr732SjbY\nImCmBgAAgMxg8gsAAIDM4LOLHH8Zl969ewd9c+bMieL40kPxJT9WXXXVoo8N6XrrrbeC9pVXXhnF\n8aWmFi9eXNBjmlnB53/66aeD9q677hrFzzzzTNDnf0SO2te9e/eg/eCDD0Zxt27dgj4/N1misba9\n+OKLURzfhXTJkiVBu3PnzlEcf61ZffXVo/hPf/pT0OeXU1A2Uxv83PjnP/9Z8P322WefoP3UU09F\nsV86I4VlEJ999llrh1gyXPkFAABAZjD5BQAAQGYw+QUAAEBmUPOb49c6HXrooUHfH//4x7z3mzhx\nYtDef//9izswJPbqq68GbX/7xrPOOivo83//P/rRj4K+a6+9ts1j6du3b9DedNNNg/att94axcuW\nLQv6vvrqqyZjZE+8dne//faL4vgSQzvssEMUd+rUqbQDQ6peeOGFoO2/vsRz5IADDgja48ePj+LP\nP/886DvvvPOi2K8Nllr3vQVUDr/23//dS+EyeO+++27BjxmvB/ffP5sT3zK5nPMlrvwCAAAgM5j8\nAgAAIDNaLHsws7GS9pI03zm3Re62LpImSOotaY6kA5xzH5VumJXL/ygd3yhX3sydOzeKd9xxx6Bv\nwYIFUdyhQ4egzz920qRJBZ9vu+22i+L4rje//e1vo3jdddcN+tZcc82gvfvuu0fxEUccEfT5H02+\n+eabQd+WW25Z8FirAa83ofjH0kOHDg3a06ZNi+KNNtoo6Kuvr4/iQj+WrFZZyBt/majhw4cHff5O\nowceeGDQ5+eBJK2yyipRHH+t83dxi/v444+jOL5rXLWqxbyJL7+59957R/Hjjz9elHOcfPLJQbvQ\n15c999yzKOcvhkKu/NZLGhC7bbSkKc65PpKm5NqAr17kDVqvXuQNWq9e5A1ar17kTSa1OPl1zj0m\n6cPYzYMkjcvF4yQNFuAhb5AEeYMkyBskQd5kV9Ka3+7Oufdy8TxJ3fMdaGYjzKzBzBr8j52RSeQN\n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\nzoOSRufq0Wpan1JxZmaSpkh6zTl3a7XHk3LkJofclITc5JCbkpCbHHJTtDRmRqrC76mmMpPw4ueR\nkhZJ+qukqxI+9jRJKyVtVdOanDGS9lDTJw8XS/q9pN0TGstQNZ32f1XSy7mvkdUaT9q/yA25ITfk\nhtyQm7R+VTMzacpNLWWGyxsDAAAgM/jAGwAAADKDyS8AAAAyg8kvAAAAMoPJLwAAADKDyS8AAAAy\ng8kvAAAAMoPJLwAAADKDyS8AAAAyg8kvAAAAMoPJLwAAADKDyS8AAAAyg8kvAAAAMoPJLwAAADKj\nrie/ZrYp9PWhmW0Jtb9YhfE8FhnTB2b2UtLjQH4pzEw3M/ulma01szVmdnXSY0DL0pab0Lg6mNki\nM3uzWmNAfmnLDa83tSGFuRlmZk+a2QYzW5L08ePYqdoDqCTnXOcdde7F/8vOud/nu7+Z7eSc21bB\n8fxX5HjPSnqkUsdD6dKWGUk/lNRO0t6SekmabWZvOud+WcFjokQpzM0OEyStUlN+kDIpzA2vNzUg\nhbnZLOn/JO0qaXwFj1M2dX3mtyVmdp2Z3WNm08xso6QzzewuM7smdJ/h4bMmZtbHzO7P/cv4DTMb\nF/PYAyQdKYkXlRpShcx8RtItzrktzrm/SbpT0rll+naQkGq81uReY06TdEuZvg0kjNcbxJF0bpxz\nf3TO3SXpjXJ+H5WU6clvzomS7pbUVdI9he5oZm0kPSxprqTeko6VdJmZDcv1H21m64o87pckPeGc\nWxZ34KiaJDNjzbQHxxw3qivp15pJki6X9F4rx43q4vUGcVRrblMTmPxKzzrnHnLOfeic29LCfY+U\n1MU5d4Nz7gPn3BJJUySdLknOuaecc91bOqCZmaSzJDW2cuyojiQz86ikCWbW2cwGSjpbUqcyfA9I\nXmK5MbNTJG11zj1UttGjWni9QRyJz21qSV2v+S1SKWde95G0t5mtD93WVtKTJR7zaEl7SPpNiY9D\nOiSZmQsl/UjSEknrJE2TdHIJx0d6JJIbM+ss6UZJ/9XSfVETeL1BHNWY29QMJr+Si7Q3y/+X7p6h\nepmkxc65A1p5zNGSfu2ce7eVz4PqSCwzzrl1kkbtaJvZLZL+FOe5UHVJ5WZ/NX1g6Q9NbzKpvaSu\nZrZK0uEstao5vN4gjmrMbWoGyx7+3cuS/tuatnzpJelrob7nJX1gZuPNrKOZtTWzg8zssGKf3Mx2\nkfQFseShnlQsM2Y2wMx2N7OdzOy/1fThk+vL/y2gCiqVm5fVNPk9OPc1VtI/cvU/yvstoAp4vUEc\nlcxNGzPrqKadQiz3HO3K/y2UD5Pff9co6TVJS9W0/ulXOzpyW4WMlPQJSW+q6W2hn0rqIklm9qnI\n2wbNOUnSWknPlHncqJ5GVS4zh0taIGmDpG9LOt0593rZvwNUQ6MqkBvn3Dbn3KodX5LelrQ9195e\nuW8HCWkUrzcoXaMql5tjJG2R9KCkfXP178r9DZSTORc9Mw4AAADUJ878AgAAIDOY/AIAACAzWjX5\nNbMRZrbQzJaY2YRyDQr1jdwgDnKDOMgN4iA39S32ml8zaytpkZquBLJcTVcGGeWc+0v5hod6Q24Q\nB7lBHOQGcZCb+teafX4/IWlJ7vrfMrNfSfqcpLzh6N69u+vXr18rDolyePPNN7Vu3broZSyTQm5q\nFLlBHLWUGzKTHi+88MI651yPKh2e3NSgUl5rWjP57S3/CiLLJR1R6AH9+vXTvHnzWnFIlENDQ0M1\nD09uahS5QRy1lBsykx5mtrSKhyc3NaiU15qKf+DNzM43s3lmNm/t2rWVPhzqBLlBHOQGpSIziIPc\n1LbWTH5XSOobavfJ3eZxzk12zjU45xp69KjWOxhIEXKDOMgN4mgxN2QGzSA3da41k9+5kgaaWX8z\nay/pdDVd3QMohNwgDnKDOMgN4iA3dS72ml/n3DYzu1DSTEltJd3hnFtQtpGhLpEbxEFuEAe5QRzk\npv615gNvcs49IumRMo0FGUFuEAe5QRzkBnGQm/rGFd4AAACQGUx+AQAAkBlMfgEAAJAZTH4BAACQ\nGUx+AQAAkBlMfgEAAJAZrdrqDACyZOvWrV77l7/8ZVCPGTMm7+P+9Kc/ee3DDjssqNu04RwEgMqY\nPn16UN90001e35e+9KWgvuiiixIbUxrwqgsAAIDMYPILAACAzGDyCwAAgMxgzS/QCh06dAjq6HrQ\nQpxzXtvMgvqUU07x+u6+++6gbtu2balDRBktWbLEa5933nlBXWjt7pAhQ7z2xo0bg7pTp05lGh0A\n+G6//fagnjdvnte3cOHCoB49erTX16VLl8oOrMo48wsAAIDMYPILAACAzMjssofo287bt2/Pe993\n3nknqKdNm1bwecNbiaxYsSLv/WbPnu21jznmmILPi+r529/+FtS33nqr17dt27agDi9daEmh+/76\n17/22h07dgzqyZMne33hZReojPfffz+oH3jggSqOBABKc8EFFwT1448/7vWFl19de+21Xt/3vve9\nyg6syjjzCwAAgMxg8gsAAIDMYPILAACAzKjrNb/h9ZiS9NxzzwX1I4884vV997vfLfvxC2199K1v\nfctrH3XUUUHNOs7q+uCDD7x2+HdVaM33Pvvs47XHjh0b1J/97Ge9vpEjR3rtv//973mf96677grq\nH/zgB14fWam8d999N6ivuuqqWM9x9dVXe+127dq1akxAWHibxfAadcnf6kqS7rvvvqB+8cUXiz7G\n5z//+aCOXiZ34MCBRT8PknXssccGdXSrzPBnnf7whz8kNqY04MwvAAAAMoPJLwAAADKj7pY9PP/8\n80F98cUXe31z585Nejh5hccpSVu2bAlq3spOXnipwze/+U2vr9BShz59+gT1E0884fWFl0FEl1Ic\neeSRXrvQsgfUvnPOOcdrs+wBrfH222977csuuyyoGxsbvb7otp7hKwqGl9u1ZMaMGUHdvn17r6+l\nLUBRPbvttltQn3vuuV7fz372s6CeP3++17d48WKvXW9LWzjzCwAAgMxg8gsAAIDMYPILAACAzKi7\nNb+PPvpoUMdd4xtdz9SzZ8+89x0/frzXXr16dVDfeOONRR8zvIXVNddcU/TjUB7hS1GXclnHZ599\nNqj79u2b937RyyLfc889JYwOQNZEt+oMb0V12mmneX1r167N+zzRdZ5XXnllUPfv3z/v4xYuXOi1\nBw0aFNTDhg3L+zik19lnn+21w2t+N23alLdPkm655ZaKjasaOPMLAACAzGhx8mtmd5jZGjObH7pt\ndzObZWaLc//tVtlhotaQG8RBbhAHuUEc5Ca7iln20ChpkqRfhG6bIGm2c+4mM5uQa19e/uGV7gtf\n+EJQ//CHP/T6dt5556Deddddvb599903qK+//nqv79BDDy36+H/605+CupRlD3WoUTWUm+nTp8d6\n3F577VXU/V5//fVYz59BjUpZbqJXzKoHc+bMCeoTTzwx7/2efvpprz1gwICKjamVGpWy3LTW5Zf7\nQ/3f//3fvPc94IADgvraa6/1+k466aSijxneQq3QNmi/+MUvvPaXv/zloo+RMo2qs9wU8tGPfrTo\n+4ZfI+pRi2d+nXNPS3orcvPnJP08V/9c0ucFhJAbxEFuEAe5QRzkJrvirvnt6ZxbmatXScr/iTDg\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x121da0048>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "images = training.sample(False, 0.01, 1).take(25)\n",
    "fig, _ = plt.subplots(5, 5, figsize = (10, 10))\n",
    "for i, ax in enumerate(fig.axes):\n",
    "    r = images[i]\n",
    "    label = r.label\n",
    "    features = r.features\n",
    "    ax.imshow(features.toArray().reshape(28, 28), cmap = \"Greys\")\n",
    "    ax.set_title(\"True: \" + str(label))\n",
    "\n",
    "plt.tight_layout()\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [],
   "source": [
    "counts = training.groupBy(\"label\").count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x120932cf8>"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1208cccf8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "counts_df = counts.rdd.map(lambda r: {\"label\": r['label'], \n",
    "                                     \"count\": r['count']}).collect()\n",
    "pd.DataFrame(counts_df).set_index(\"label\").sort_index().plot.bar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df_testing = (spark\n",
    "              .read\n",
    "              .options(header = False, inferSchema = True)\n",
    "              .csv(\"data/MNIST/mnist_test.csv\"))\n",
    "testing = (vectorizer\n",
    "           .transform(df_testing)\n",
    "           .select(\"_c0\", \"features\")\n",
    "           .toDF(\"label\", \"features\")\n",
    "           .cache())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pyspark.ml.classification import LogisticRegression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "lr = LogisticRegression(featuresCol=\"features\", \n",
    "                        labelCol=\"label\", \n",
    "                        regParam=0.1, \n",
    "                        elasticNetParam=0.1, \n",
    "                        maxIter=10000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "lr_model = lr.fit(training)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pyspark.sql.functions import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-----+--------------------+--------------------+--------------------+----------+-------+\n",
      "|label|            features|       rawPrediction|         probability|prediction|matched|\n",
      "+-----+--------------------+--------------------+--------------------+----------+-------+\n",
      "|    7|(784,[202,203,204...|[0.08070480165374...|[0.01163236392094...|       7.0|   true|\n",
      "|    2|(784,[94,95,96,97...|[1.25425406358765...|[0.02467764471716...|       2.0|   true|\n",
      "|    1|(784,[128,129,130...|[-1.2276524471687...|[0.00751263994471...|       1.0|   true|\n",
      "|    0|(784,[124,125,126...|[3.71476062530585...|[0.85536145424016...|       0.0|   true|\n",
      "|    4|(784,[150,151,159...|[-0.2039270192761...|[0.04549113250992...|       4.0|   true|\n",
      "|    1|(784,[156,157,158...|[-1.8454996939466...|[0.00278444647289...|       1.0|   true|\n",
      "|    4|(784,[149,150,151...|[-1.7871799792661...|[0.00965258005973...|       4.0|   true|\n",
      "|    9|(784,[179,180,181...|[-2.3331144616742...|[0.00711927716793...|       9.0|   true|\n",
      "|    5|(784,[129,130,131...|[0.25089606477712...|[0.06160565780450...|       5.0|   true|\n",
      "|    9|(784,[209,210,211...|[-0.7976271976762...|[0.02088880010781...|       9.0|   true|\n",
      "|    0|(784,[123,124,125...|[3.87665582702822...|[0.80110751027447...|       0.0|   true|\n",
      "|    6|(784,[94,95,96,97...|[1.89086135619814...|[0.28924960656629...|       0.0|  false|\n",
      "|    9|(784,[208,209,210...|[-1.4656858164681...|[0.00902667735258...|       9.0|   true|\n",
      "|    0|(784,[152,153,154...|[3.52162978716862...|[0.84049195109150...|       0.0|   true|\n",
      "|    1|(784,[125,126,127...|[-2.2951507253657...|[0.00159973133619...|       1.0|   true|\n",
      "|    5|(784,[124,125,126...|[0.26443714870398...|[0.07367353100470...|       5.0|   true|\n",
      "|    9|(784,[179,180,181...|[-0.6255916188595...|[0.02550361387932...|       9.0|   true|\n",
      "|    7|(784,[200,201,202...|[0.70990611838535...|[0.02075121690891...|       7.0|   true|\n",
      "|    3|(784,[118,119,120...|[-1.0216859510239...|[0.01042092765356...|       3.0|   true|\n",
      "|    4|(784,[158,159,185...|[-1.2147078347317...|[0.01415523283792...|       4.0|   true|\n",
      "+-----+--------------------+--------------------+--------------------+----------+-------+\n",
      "only showing top 20 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "test_pred = lr_model.transform(testing).withColumn(\"matched\", expr(\"label == prediction\"))\n",
    "test_pred.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pyspark.ml.evaluation import MulticlassClassificationEvaluator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "evaluator = MulticlassClassificationEvaluator(labelCol=\"label\", \n",
    "                                               predictionCol=\"prediction\", \n",
    "                                               metricName=\"accuracy\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8729"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluator.evaluate(test_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-----+------------------+\n",
      "|label|      avg(matched)|\n",
      "+-----+------------------+\n",
      "|    0|0.9622448979591837|\n",
      "|    1|0.9718061674008811|\n",
      "|    2|0.8275193798449613|\n",
      "|    3|0.8772277227722772|\n",
      "|    4|0.8940936863543788|\n",
      "|    5|0.7600896860986547|\n",
      "|    6|0.9050104384133612|\n",
      "|    7|0.8735408560311284|\n",
      "|    8|0.7895277207392197|\n",
      "|    9|0.8453914767096135|\n",
      "+-----+------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "(test_pred\n",
    " .withColumn(\"matched\", expr(\"cast(matched as int)\"))\n",
    " .groupby(\"label\")\n",
    " .agg(avg(\"matched\"))\n",
    " .orderBy(\"label\")\n",
    " .show())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Classifying MNIST using Neural Networks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pyspark.ml.classification import MultilayerPerceptronClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "layers = [784, 100, 20, 10]\n",
    "perceptron = MultilayerPerceptronClassifier(maxIter=1000, layers=layers, blockSize=128, seed=1234)\n",
    "perceptron_model = perceptron.fit(training)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from time import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "start_time = time()\n",
    "perceptron_model = perceptron.fit(training)\n",
    "test_pred = perceptron_model.transform(testing)\n",
    "print(\"Accuracy:\", evaluator.evaluate(test_pred))\n",
    "print(\"Time taken: %d\" % (time() - start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
